﻿Option Strict On
Imports System.Data.OleDb
Imports System.IO
Imports ADOX
Imports Microsoft.Office.Interop
Imports OleDbConnection = System.Data.OleDb.OleDbConnection

Module 手集計

#Region "DB新規作成・削除・閉じる テーブル"
    '＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
    'MyDB新規作成
    '＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
    Public Sub Db新規作成(ByVal Mydb As String)
        If String.IsNullOrWhiteSpace(Mydb) Then
            Throw New ArgumentException("Mydb に有効なパスを指定してください。", NameOf(Mydb))
        End If

        Try
            ' 既存ファイルの削除前に COM オブジェクトを強制解放
            If File.Exists(Mydb) Then
                ' 1. Access プロセスを強制終了
                Try
                    Dim accessProcesses = Process.GetProcessesByName("MSACCESS")
                    For Each proc In accessProcesses
                        Try
                            proc.Kill()
                            proc.WaitForExit(2000)
                        Catch
                        End Try
                    Next
                Catch
                End Try

                ' 2. ガベージコレクションを強制実行
                For i As Integer = 1 To 2
                    GC.Collect()
                    GC.WaitForPendingFinalizers()
                Next

                ' 3. ロックファイル (.laccdb) を削除
                Dim lockFile As String = Path.ChangeExtension(Mydb, ".laccdb")
                If File.Exists(lockFile) Then
                    Try
                        File.Delete(lockFile)
                    Catch
                        ' ロックファイルの削除失敗は無視
                    End Try
                End If

                System.Threading.Thread.Sleep(1000)

                ' 4. データベースファイル削除をリトライ
                Dim deleted As Boolean = False
                For i As Integer = 1 To 5
                    Try
                        File.Delete(Mydb)
                        deleted = True
                        Exit For
                    Catch ex As IOException
                        If i < 5 Then
                            System.Threading.Thread.Sleep(1000)
                            GC.Collect()
                            GC.WaitForPendingFinalizers()
                        Else
                            ' 最終的に失敗した場合、詳細なエラーメッセージを表示
                            Throw New IOException(
                                $"データベースファイルを削除できません。{vbCrLf}" &
                                $"パス: {Mydb}{vbCrLf}" &
                                $"以下を確認してください:{vbCrLf}" &
                                $"1. Accessアプリケーションが開いていないか{vbCrLf}" &
                                $"2. エクスプローラーでファイルを開いていないか{vbCrLf}" &
                                $"3. 他のプログラムがファイルを使用していないか{vbCrLf}" &
                                $"元のエラー: {ex.Message}", ex)
                        End If
                    End Try
                Next
            End If

            ' ADOX.Catalog のインスタンス生成
            ' ※参照設定で「Microsoft ADO Ext. x.x for DDL and Security」が必要です
            Dim cat As Object = CreateObject("ADOX.Catalog")

            Try
                Dim connStr As String = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={Mydb};"
                ' データベース作成
                CallByName(cat, "Create", CallType.Method, connStr)
            Finally
                ' COM オブジェクトの確実な解放
                If cat IsNot Nothing Then
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(cat)
                    cat = Nothing
                End If
            End Try

        Catch ex As Exception
            ' 呼び出し元へエラーを再送
            Throw
        End Try

    End Sub
    '＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
    ' MyDBのファイルサイズがSaizu(MB)以上であればAccessデータベースを最適化する
    '＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝
    Public Sub Access最適化(MyDB As String, Saizu As Integer)
        If Not File.Exists(MyDB) Then Exit Sub

        Dim fi As New FileInfo(MyDB)
        If fi.Length < CLng(Saizu) * 1024L * 1024L Then Exit Sub

        Dim tempPath As String = MyDB & ".tmp"
        Try
            Dim compacted As Boolean = False

            ' Try JRO (Jet Replication Objects)
            Dim jro As Object = Nothing
            Try
                jro = CreateObject("JRO.JetEngine")
                Dim args As Object() = {
                    "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB,
                    "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & tempPath
                }
                jro.GetType().InvokeMember("CompactDatabase",
                    Reflection.BindingFlags.InvokeMethod,
                    Nothing, jro, args)
                compacted = True
            Catch
                ' ignore and try DAO below
            Finally
                If jro IsNot Nothing Then
                    Try
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(jro)
                    Catch
                    End Try
                    jro = Nothing
                End If
            End Try

            ' Fallback: try DAO compact (if available)
            If Not compacted Then
                Try
                    Dim dbe As Object = CreateObject("DAO.DBEngine.120")
                    ' DAO.CompactDatabase requires source and destination paths
                    Dim args As Object() = {MyDB, tempPath}
                    dbe.GetType().InvokeMember("CompactDatabase",
                        Reflection.BindingFlags.InvokeMethod,
                        Nothing, dbe, args)
                    compacted = True
                    Try
                        System.Runtime.InteropServices.Marshal.ReleaseComObject(dbe)
                    Catch
                    End Try
                    dbe = Nothing
                Catch
                    ' ignore, will raise error below if not compacted
                End Try
            End If

            If Not compacted Then
                Throw New Exception("データベースの最適化に失敗しました。JRO/DAO コンポーネントが利用できないか、プロバイダのビット数が一致していない可能性があります。")
            End If

            File.Delete(MyDB)
            File.Move(tempPath, MyDB)
        Catch ex As Exception
            If File.Exists(tempPath) Then File.Delete(tempPath)
            MsgBox("Access最適化エラー: " & ex.Message)
        End Try
    End Sub

    ''' <summary>
    ''' 指定テーブルの列名を変更します。まず ADOX で列名を直接変更し、失敗した場合は
    ''' ALTER TABLE で新しい列を追加してコピー、旧列を削除するフォールバックを行います。
    ''' </summary>
    Public Sub Rename判定ToE判定()
        Dim tableName As String = "T160_全出荷E集計"
        If String.IsNullOrWhiteSpace(MyDB) Then
            MsgBox("DBパス未設定のため列名変更を中止します。")
            Return
        End If

        Dim cat As ADOX.Catalog = Nothing
        Try
            cat = New ADOX.Catalog()
            cat.let_ActiveConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")

            Dim tbl As ADOX.Table = Nothing
            For i As Integer = 0 To cat.Tables.Count - 1
                If String.Equals(cat.Tables(i).Name, tableName, StringComparison.OrdinalIgnoreCase) Then
                    tbl = cat.Tables(i)
                    Exit For
                End If
            Next

            If tbl Is Nothing Then
                MsgBox("テーブル '" & tableName & "' が見つかりません。")
                Return
            End If

            Dim hasOld As Boolean = False
            Dim hasNew As Boolean = False
            For j As Integer = 0 To tbl.Columns.Count - 1
                Dim cname As String = tbl.Columns(j).Name
                If String.Equals(cname, "判定", StringComparison.OrdinalIgnoreCase) Then hasOld = True
                If String.Equals(cname, "E判定", StringComparison.OrdinalIgnoreCase) Then hasNew = True
            Next

            If hasNew Then
                ' 既にE判定があるので何もしない
                Return
            End If

            If hasOld Then
                Try
                    ' ADOX で直接変更を試みる
                    tbl.Columns.Item("判定").Name = "E判定"
                    MsgBox("列名を '判定' -> 'E判定' に変更しました。")
                    Return
                Catch ex As Exception
                    ' フォールバックへ
                End Try
            Else
                MsgBox("列 '判定' が見つかりません。")
                Return
            End If

            ' フォールバック: 新列追加、値コピー、旧列削除
            Try
                Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                    cn.Open()
                    Using addCmd As New OleDbCommand("ALTER TABLE [" & tableName & "] ADD COLUMN [E判定] TEXT(10)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                    Using updCmd As New OleDbCommand("UPDATE [" & tableName & "] SET [E判定] = [判定]", cn)
                        updCmd.ExecuteNonQuery()
                    End Using
                    Using dropCmd As New OleDbCommand("ALTER TABLE [" & tableName & "] DROP COLUMN [判定]", cn)
                        dropCmd.ExecuteNonQuery()
                    End Using
                    cn.Close()
                End Using
                MsgBox("フォールバックにより '判定' を 'E判定' に移行しました。")
            Catch ex As Exception
                MsgBox("列名変更に失敗しました: " & ex.Message)
            End Try

        Catch ex As Exception
            MsgBox("Rename 判定 -> E判定 エラー: " & ex.Message)
        Finally
            ReleaseCom(cat)
        End Try
    End Sub

    ''' <summary>
    ''' T160_全出荷I集計 テーブルの列名 '判定' を 'I判定' に変更します。
    ''' ADOXで直接リネームを試み、失敗した場合はフォールバックで新列追加・コピー・旧列削除を行います。
    ''' </summary>
    Public Sub Rename判定ToI判定()
        Dim tableName As String = "T160_全出荷I集計"
        If String.IsNullOrWhiteSpace(MyDB) Then
            MsgBox("DBパス未設定のため列名変更を中止します。")
            Return
        End If

        Dim cat As ADOX.Catalog = Nothing
        Try
            cat = New ADOX.Catalog()
            cat.let_ActiveConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")

            Dim tbl As ADOX.Table = Nothing
            For i As Integer = 0 To cat.Tables.Count - 1
                If String.Equals(cat.Tables(i).Name, tableName, StringComparison.OrdinalIgnoreCase) Then
                    tbl = cat.Tables(i)
                    Exit For
                End If
            Next

            If tbl Is Nothing Then
                MsgBox("テーブル '" & tableName & "' が見つかりません。")
                Return
            End If

            Dim hasOld As Boolean = False
            Dim hasNew As Boolean = False
            For j As Integer = 0 To tbl.Columns.Count - 1
                Dim cname As String = tbl.Columns(j).Name
                If String.Equals(cname, "判定", StringComparison.OrdinalIgnoreCase) Then hasOld = True
                If String.Equals(cname, "I判定", StringComparison.OrdinalIgnoreCase) Then hasNew = True
            Next

            If hasNew Then
                ' 既に I判定 があるので何もしない
                Return
            End If

            If hasOld Then
                Try
                    tbl.Columns.Item("判定").Name = "I判定"
                    MsgBox("列名を '判定' -> 'I判定' に変更しました。")
                    Return
                Catch ex As Exception
                    ' フォールバックへ
                End Try
            Else
                MsgBox("列 '判定' が見つかりません。")
                Return
            End If

            ' フォールバック: 新列追加、値コピー、旧列削除
            Try
                Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                    cn.Open()
                    Using addCmd As New OleDbCommand("ALTER TABLE [" & tableName & "] ADD COLUMN [I判定] TEXT(10)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                    Using updCmd As New OleDbCommand("UPDATE [" & tableName & "] SET [I判定] = [判定]", cn)
                        updCmd.ExecuteNonQuery()
                    End Using
                    Using dropCmd As New OleDbCommand("ALTER TABLE [" & tableName & "] DROP COLUMN [判定]", cn)
                        dropCmd.ExecuteNonQuery()
                    End Using
                    cn.Close()
                End Using
                MsgBox("フォールバックにより '判定' を 'I判定' に移行しました。")
            Catch ex As Exception
                MsgBox("列名変更に失敗しました: " & ex.Message)
            End Try

        Catch ex As Exception
            MsgBox("Rename 判定 -> I判定 エラー: " & ex.Message)
        Finally
            ReleaseCom(cat)
        End Try
    End Sub
    Public Sub Access閉じる(MyDB1 As String)
        Dim targetFileName As String = MyDB1
        Dim accessApp As Access.Application = Nothing

        Try
            accessApp = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Access.Application"), Access.Application)

            If accessApp.CurrentProject.Name = targetFileName Then
                accessApp.Quit()
                Console.WriteLine($"{targetFileName} を終了しました。")
            End If

        Catch ex As System.Runtime.InteropServices.COMException
            ' Accessが起動していない場合は何もしない
        Finally
            If accessApp IsNot Nothing Then
                System.Runtime.InteropServices.Marshal.ReleaseComObject(accessApp)
            End If
        End Try
    End Sub
    Public Sub Access接続を確実に閉じる(MyDB As String)
        ' インポートの直前にこれを徹底してください
        GC.Collect()
        GC.WaitForPendingFinalizers()

        ' CreateObjectを使用してインスタンス化
        Dim accessApp As Access.Application = DirectCast(CreateObject("Access.Application"), Access.Application)
        Try
            ' OpenCurrentDatabase の前にファイルが存在し、ロックされていないか確認
            ' 排他モード(Exclusive:=False)で開くことで衝突を避ける
            accessApp.OpenCurrentDatabase(MyDB, Exclusive:=False)

            ' ... インポート処理 ...
        Catch ex As Exception
            ' エラー詳細を表示
            Console.WriteLine("実行エラー: " & ex.Message)
        Finally
            accessApp.Quit()
            System.Runtime.InteropServices.Marshal.ReleaseComObject(accessApp)
        End Try

    End Sub

#End Region

#Region "テーブル 作成・削除・項目追加・削除"

    ''' <summary>
    ''' Accessテーブルに新しい列を追加します。
    ''' </summary>
    Public Sub 列を追加(dbPath As String, テーブル名 As String, 列名 As String, データ型 As String)

        '<param name="dbPath">Accessファイルへのフルパス</param>
        '<param name="テーブル名">対象のテーブル名</param>
        '<param name="列名">追加したい新しい列名</param>
        '<param name="データ型">String, Double, Integer など</param>
        '
        '接続文字列（accdb形式用）
        Dim connStr As String = $"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={dbPath};"

        ' SQL上のデータ型に変換
        Dim sqlDataType As String = GetSqlDataType(データ型)

        ' SQL文の作成（ALTER TABLE テーブル名 ADD COLUMN 列名 型）
        Dim sql As String = $"ALTER TABLE [{テーブル名}] ADD COLUMN [{列名}] {sqlDataType}"

        Using conn As New OleDbConnection(connStr)
            Try
                conn.Open()
                Using cmd As New OleDbCommand(sql, conn)
                    cmd.ExecuteNonQuery()
                End Using
                Console.WriteLine("列が正常に追加されました。")
            Catch ex As Exception
                MsgBox("エラーが発生しました: " & ex.Message)
            End Try
        End Using
    End Sub
    '' <summary>
    '' 引数の文字列をAccess SQLのデータ型キーワードに変換します。
    ''' 列を追加(dbPath As String, テーブル名 As String,列名 As String, データ型 As String)から呼び出される
    ''' </summary>
    Private Function GetSqlDataType(dataType As String) As String
        Select Case dataType.ToLower()
            Case "string", "文字型", "テキスト"
                Return "LONGTEXT" ' または VARCHAR(255)
            Case "double", "数値", "実数"
                Return "DOUBLE"
            Case "integer", "整数"
                Return "INTEGER"
            Case "date", "日付"
                Return "DATETIME"
            Case "boolean", "真偽値"
                Return "YESNO"
            Case Else
                Return "VARCHAR(255)"
        End Select
    End Function

#End Region

#Region "DB ImportExce ExportExcel"
    Public Sub ImportExcelToAccess(MyDB As String, MyTable As String, MyExcel As String, MySheet As String)
        Dim dbPath As String = MyDB
        Dim excelPath As String = MyExcel
        Dim tableName As String = MyTable

        ' CreateObjectを使用してインスタンス化（他のメソッドと統一）
        Dim accessApp As Access.Application = DirectCast(CreateObject("Access.Application"), Access.Application)

        Try
            ' データベースを排他モードで開く
            accessApp.OpenCurrentDatabase(dbPath)

            ' 1. 同名テーブルが既にある場合は削除（リフレッシュするため）
            Try
                accessApp.DoCmd.DeleteObject(Access.AcObjectType.acTable, tableName)
            Catch
                ' テーブルが存在しないエラーは無視
            End Try

            ' 2. Excelインポート実行
            ' acImport: インポート, acSpreadsheetTypeExcel12Xml: .xlsx, True: 1行目をヘッダーとする
            accessApp.DoCmd.TransferSpreadsheet(
                Access.AcDataTransferType.acImport,
                Access.AcSpreadSheetType.acSpreadsheetTypeExcel12Xml,
                tableName,
                excelPath,
                HasFieldNames:=True
            )

            Console.WriteLine($"テーブル [{tableName}] の作成とインポートが完了しました。")

        Catch ex As Exception
            Console.WriteLine("実行エラー: " & ex.Message)
        Finally
            accessApp.Quit()
            System.Runtime.InteropServices.Marshal.ReleaseComObject(accessApp)
        End Try
    End Sub

#End Region

#Region "Access Query・Table削除 サーチ等”
    Public Sub DEL_Query(ByVal Query名 As String)

        '呼び出し例 DEL_Query(Q12＊）ー－＞Q12ｘｘｘはすべて削除

        'MsgBox(Query名)
        Dim cn As ADODB.Connection = DirectCast(CreateObject("ADODB.Connection"), ADODB.Connection)
        Dim cat As ADOX.Catalog
        Dim viw As ADOX.View
        'Dim tbl As ADOX.Table
        cn.ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + MyDB + ";"
        cn.Open()
        cat = DirectCast(CreateObject("ADOX.Catalog"), ADOX.Catalog)
        cat.let_ActiveConnection(cn)  ' cn は ADODB.Connection オブジェクト

        Dim h(50) As String
        Dim f As Integer = 0
        Dim i As Integer = 0
        Dim L = Query名.Length
        If InStr(Query名, "*") >= 2 Then
            L = InStr(Query名, "*") - 1
            Query名 = Strings.Left(Query名, L)
        End If


        For Each viw In cat.Views
            If Strings.Left(viw.Name, L) = Query名 Then
                f += 1 : h(f) = viw.Name           'クエリー検索
            End If
        Next viw

        'For Each tbl In cat.Tables
        '    If tbl.Type = "TABLE" Then
        '        .Items.Add(tbl.Name)        'テーブル検索
        '    End If
        'Next


        For i = 1 To f
            cn.Execute("DROP VIEW " & h(i) & "") 'クエリー削除
        Next

        If cat IsNot Nothing Then
            Try
                System.Runtime.InteropServices.Marshal.ReleaseComObject(cat)
            Catch
            End Try
            cat = Nothing
        End If
        cn.Close()
        If cn IsNot Nothing Then
            Try
                System.Runtime.InteropServices.Marshal.ReleaseComObject(cn)
            Catch
            End Try
            cn = Nothing
        End If

    End Sub

    Public Sub DEL_table(ByVal Table名 As String)

        '呼び出し例 DEL_table(Ｔ12*）ー－＞Ｔ12ｘｘｘはすべて削除

        Dim cn As ADODB.Connection = Nothing
        Dim cat As ADOX.Catalog = Nothing
        If Table名 Is Nothing Then Return
        Dim a As String = If(Table名.Length >= 2, Table名.Substring(0, 2), Table名)
        If a = "MS" Or a = "ms" Then
            MsgBox("システムテーブルは削除不可")
            Return
        End If

        Try
            cn = New ADODB.Connection()
            cn.Open("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
            cat = New ADOX.Catalog()
            cat.let_ActiveConnection(cn)

            Dim L As Integer = If(Table名.Contains("*"), Table名.IndexOf("*"), Table名.Length)
            Dim prefix As String = Table名.Substring(0, L)

            ' 逆順で削除（インデックス変動対策）
            For i As Integer = cat.Tables.Count - 1 To 0 Step -1
                Dim tblName As String = cat.Tables(i).Name
                If tblName.StartsWith(prefix) Then
                    ' ADODB.Connection 経由で DROP TABLE 実行（安全）
                    cn.Execute("DROP TABLE [" & tblName & "]")
                End If
            Next
        Catch ex As Exception
            MessageBox.Show("DEL_table エラー: " & ex.Message)
        Finally
            Try
                If cn IsNot Nothing AndAlso cn.State = 1 Then cn.Close()
            Catch
            End Try
            ReleaseCom(cat)
            ReleaseCom(cn)
            GC.Collect()
            GC.WaitForPendingFinalizers()
        End Try
    End Sub
    ''' <summary>
    ''' COMオブジェクトを安全に解放します。
    ''' </summary>
    Private Sub ReleaseCom(ByVal obj As Object)
        Try
            If obj IsNot Nothing AndAlso System.Runtime.InteropServices.Marshal.IsComObject(obj) Then
                System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
            End If
        Catch
        Finally
            obj = Nothing
        End Try
    End Sub


    Public Function Search_Table(ByVal Table名 As String) As Boolean
        Dim a As String = Table名.Substring(0, 2)
        If a = "MS" Or a = "ms" Then
            MsgBox("システムテーブルは対象外")
            Return False
        End If

        Dim ADOXDBCon As ADOX.Catalog = Nothing
        Try
            ADOXDBCon = New ADOX.Catalog()
            ' 修正: let_ActiveConnection メソッドを使用
            ADOXDBCon.let_ActiveConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")

            Dim i As Integer = 0
            Dim L As Integer = Table名.Length

            If a.Contains("*") = True Then
                If InStr(Table名, "*") >= 2 Then
                    L = InStr(Table名, "*") - 1
                    Table名 = Strings.Left(Table名, L)
                End If
                For i = 0 To ADOXDBCon.Tables.Count - 1
                    If Strings.Left(ADOXDBCon.Tables(i).Name, L) = Table名 Then
                        Return True
                    End If
                Next
            End If

            If a.Contains("*") = False Then
                For i = 0 To ADOXDBCon.Tables.Count - 1
                    If Table名 = ADOXDBCon.Tables(i).Name Then
                        Return True
                    End If
                Next
            End If

            Return False
        Catch ex As Exception
            MsgBox("Search_Table エラー: " & ex.Message)
            Return False
        Finally
            ' COM オブジェクトの適切な解放
            ReleaseCom(ADOXDBCon)
        End Try
    End Function

    ' EnsureColumnExists removed: direct ALTER TABLE attempts are used instead per user's preference


#End Region

#Region "  SQL実行”
    Public Sub Sqlcommands_Add(sqlCommands As List(Of String))
        Dim cn As System.Data.OleDb.OleDbConnection =
                  New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
        Dim Com As System.Data.OleDb.OleDbCommand = New OleDb.OleDbCommand()
        Com.Connection = cn
        cn.Open()
        Com.Transaction = cn.BeginTransaction
        Try
            Dim i1 As Integer
            For i1 = 0 To sqlCommands.Count - 1
                Com.CommandText = sqlCommands(i1)
                Com.ExecuteNonQuery()
            Next
            Com.Transaction.Commit()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
            Com.Transaction.Rollback()
        Finally
            cn.Close()
        End Try

    End Sub
    Public Sub SQL実行(ByVal MySql As String)
        ' 実行専用：UPDATE/INSERT/DELETE などの非クエリを正しく実行するため ExecuteNonQuery を使用します。
        Using con As New OleDb.OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
            Using cmd As New OleDb.OleDbCommand(MySql, con)
                cmd.CommandType = CommandType.Text
                Try
                    con.Open()
                    Dim affected As Integer = cmd.ExecuteNonQuery()
                    ' 影響行数をログ出力（デバッグ用）。必要なければ削除可。
                    ' Debug.WriteLine($"SQL実行: {MySql} -> {affected} 行")
                Catch ex As Exception
                    Try
                        MessageBox.Show("SQL実行エラー: " & ex.Message & vbCrLf & "SQL: " & MySql)
                    Catch
                    End Try
                    Throw
                End Try
            End Using
        End Using
    End Sub



#End Region
    Public Sub T150からT750作成()
        If String.IsNullOrWhiteSpace(MyDB) Then
            MsgBox("DBパスが未設定のため T150->T750 作成を中止します。")
            Return
        End If

        Try
            ' 既存の T750* テーブルは削除しておく
            Try
                DEL_table("T750*")
            Catch
            End Try

            Dim catalog As New ADOX.Catalog()
            catalog.let_ActiveConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")

            For i As Integer = 0 To catalog.Tables.Count - 1
                Try
                    Dim tname As String = catalog.Tables(i).Name.ToString()
                    If tname Is Nothing Then Continue For
                    If tname.StartsWith("T150", StringComparison.OrdinalIgnoreCase) Then
                        Dim newName As String = "T750" & tname.Substring(4)

                        ' 削除されていなければ個別に削除
                        If Search_Table(newName) Then
                            Try
                                DEL_table(newName)
                            Catch
                            End Try
                        End If

                        ' テーブルをコピー (SELECT INTO を使用)
                        Try
                            Dim MySQL As String = "SELECT * INTO [" & newName & "] FROM [" & tname & "]"
                            SQL実行(MySQL)
                        Catch ex As Exception
                            ' 個別テーブルのコピー失敗はログを残して次へ
                        End Try
                    End If
                Catch
                    ' 個別参照失敗は無視
                End Try
            Next

        Catch ex As Exception
            MsgBox("T150->T750 作成中にエラーが発生しました: " & ex.Message)
        End Try

    End Sub
    Public Sub T160からT760作成()

    End Sub

    Public Sub T760_全出荷E集計作成(Table名 As String, 計算E数 As Integer, E採用判定値 As Double)
        Dim sval As Double
        Dim MySQL As String = ""

        ' Try to add ECHK column; ignore errors if it already exists or cannot be added
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Try
                    Using addCmd As New OleDbCommand("ALTER TABLE [" & Table名 & "] ADD COLUMN [ECHK] TEXT(1)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                Catch
                    ' ignore if column exists or cannot be added
                End Try
                cn.Close()
            End Using
        Catch
        End Try
        If E採用判定値 > 1 Then
            sval = E採用判定値 - 1
            MySQL = "UPDATE [" & Table名 & "] SET [E判定] = IIf([乱数] <= " & sval & ", 'Yes', 'No'),[ECHK] = '*';"
        Else
            sval = E採用判定値
            MySQL = "UPDATE [" & Table名 & "] SET [E判定] = IIf([乱数] <= " & sval & ", 'Yes', 'No'),[ECHK] = '';"
        End If

        SQL実行(MySQL)
    End Sub
    Public Sub T760_全出荷I集計作成(Table名 As String, 計算I数 As Integer, I採用判定値 As Double)
        Dim sval As Double
        Dim MySQL As String = ""

        ' Try to add ICHK column; ignore errors if it already exists or cannot be added
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Try
                    Using addCmd As New OleDbCommand("ALTER TABLE [" & Table名 & "] ADD COLUMN [ICHK] TEXT(1)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                Catch
                    ' ignore if column exists or cannot be added
                End Try
                cn.Close()
            End Using
        Catch
        End Try
        If I採用判定値 > 1 Then
            sval = I採用判定値 - 1
            MySQL = "UPDATE [" & Table名 & "] SET [I判定] = IIf([乱数] <= " & sval & ", 'Yes', 'No'),[ICHK] = '*';"
        Else
            sval = I採用判定値
            MySQL = "UPDATE [" & Table名 & "] SET [I判定] = IIf([乱数] <= " & sval & ", 'Yes', 'No'),[ICHK] = '';"
        End If

        SQL実行(MySQL)
    End Sub

    Public Sub T900_計算対象作成(進行連番 As Integer, E採用判定値 As Double, I採用判定値 As Double)
        ' 1. T900* テーブルを削除
        DEL_table("T900*")

        ' 2. T900_計算対象 を新規作成（指定列定義）
        MySQL = "CREATE TABLE T900_計算対象 (" &
                "進行連番 INTEGER, " &
                "GPLEランク TEXT(10), " &
                "GPLIランク TEXT(10), " &
                "行連番 INTEGER, " &
                "出荷先 TEXT(20), " &
                "アイテム TEXT(20), " &
                "G行 DOUBLE, " &
                "Gバ DOUBLE, " &
                "Gケ DOUBLE, " &
                "GPL DOUBLE, " &
                "G容 DOUBLE, " &
                "G重 DOUBLE)"
        SQL実行(MySQL)

        ' 3. 採用判定値に応じてデータを投入
        If E採用判定値 <= 1 And I採用判定値 <= 1 Then
            ' E・I ともに全採用（乱数フィルタのみ）
            ' T200 を T760_全出荷E集計（出荷先）・T760_全出荷I集計（アイテム）と結合し
            ' E判定='Yes' かつ I判定='Yes' のレコードを T900_計算対象 へ挿入
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計 ON T200.出荷先 = T760_全出荷E集計.出荷先) " &
                    "INNER JOIN T760_全出荷I集計 ON T200.アイテム = T760_全出荷I集計.アイテム " &
                    "WHERE T760_全出荷E集計.E判定 = 'Yes' AND T760_全出荷I集計.I判定 = 'Yes';"
            SQL実行(MySQL)
        End If

        If E採用判定値 > 1 And I採用判定値 <= 1 Then
            ' 1. E採用判定値A = E採用判定値 - 1 で T760_全出荷E集計A を作成
            Dim E採用判定値A As Double = E採用判定値 - 1
            T760_全出荷E集計A作成(E採用判定値A)

            ' 2. T760_全出荷E集計A（E判定=Yes）× T760_全出荷I集計（I判定=Yes）
            '    出荷先に "A" を付加してレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先 & 'A', T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計A ON T200.出荷先 = T760_全出荷E集計A.出荷先) " &
                    "INNER JOIN T760_全出荷I集計 ON T200.アイテム = T760_全出荷I集計.アイテム " &
                    "WHERE T760_全出荷E集計A.E判定 = 'Yes' AND T760_全出荷I集計.I判定 = 'Yes';"
            SQL実行(MySQL)

            ' 3. T760_全出荷E集計（E判定 Yes/No 問わず）× T760_全出荷I集計（I判定=Yes）
            '    出荷先はそのままレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計 ON T200.出荷先 = T760_全出荷E集計.出荷先) " &
                    "INNER JOIN T760_全出荷I集計 ON T200.アイテム = T760_全出荷I集計.アイテム " &
                    "WHERE T760_全出荷I集計.I判定 = 'Yes';"
            SQL実行(MySQL)
        End If

        If E採用判定値 <= 1 And I採用判定値 > 1 Then
            ' 1. I採用判定値A = I採用判定値 - 1 で T760_全出荷I集計A を作成
            Dim I採用判定値A As Double = I採用判定値 - 1
            T760_全出荷I集計A作成(I採用判定値A)

            ' 2. T760_全出荷I集計A（I判定=Yes）× T760_全出荷E集計（E判定=Yes）
            '    アイテムに "A" を付加してレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム & 'A', " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計 ON T200.出荷先 = T760_全出荷E集計.出荷先) " &
                    "INNER JOIN T760_全出荷I集計A ON T200.アイテム = T760_全出荷I集計A.アイテム " &
                    "WHERE T760_全出荷I集計A.I判定 = 'Yes' AND T760_全出荷E集計.E判定 = 'Yes';"
            SQL実行(MySQL)

            ' 3. T760_全出荷I集計（I判定 Yes/No 問わず）× T760_全出荷E集計（E判定=Yes）
            '    アイテムはそのままレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計 ON T200.出荷先 = T760_全出荷E集計.出荷先) " &
                    "INNER JOIN T760_全出荷I集計 ON T200.アイテム = T760_全出荷I集計.アイテム " &
                    "WHERE T760_全出荷E集計.E判定 = 'Yes';"
            SQL実行(MySQL)
        End If

        If E採用判定値 > 1 And I採用判定値 > 1 Then
            ' 1. A テーブルを両方作成
            Dim I採用判定値A As Double = I採用判定値 - 1
            T760_全出荷I集計A作成(I採用判定値A)
            Dim E採用判定値A As Double = E採用判定値 - 1
            T760_全出荷E集計A作成(E採用判定値A)

            ' 2a. T760_全出荷I集計A（I判定=Yes）× T760_全出荷E集計（E判定=Yes）
            '     アイテムに "A" を付加してレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム & 'A', " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計 ON T200.出荷先 = T760_全出荷E集計.出荷先) " &
                    "INNER JOIN T760_全出荷I集計A ON T200.アイテム = T760_全出荷I集計A.アイテム " &
                    "WHERE T760_全出荷I集計A.I判定 = 'Yes' AND T760_全出荷E集計.E判定 = 'Yes';"
            SQL実行(MySQL)

            ' 2b. T760_全出荷E集計A（E判定=Yes）× T760_全出荷I集計（I判定=Yes）
            '     出荷先に "A" を付加してレコード追加
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先 & 'A', T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM (T200 " &
                    "INNER JOIN T760_全出荷E集計A ON T200.出荷先 = T760_全出荷E集計A.出荷先) " &
                    "INNER JOIN T760_全出荷I集計 ON T200.アイテム = T760_全出荷I集計.アイテム " &
                    "WHERE T760_全出荷E集計A.E判定 = 'Yes' AND T760_全出荷I集計.I判定 = 'Yes';"
            SQL実行(MySQL)

            ' 3. T200 全レコードをそのまま追加（E/I 判定条件なし）
            MySQL = "INSERT INTO T900_計算対象 " &
                    "(進行連番, 行連番, 出荷先, アイテム, G行, Gバ, Gケ, GPL, G容, G重) " &
                    "SELECT " & 進行連番 & ", T200.行連番, T200.出荷先, T200.アイテム, " &
                    "T200.G行, T200.Gバ, T200.Gケ, T200.GPL, T200.G容, T200.G重 " &
                    "FROM T200;"
            SQL実行(MySQL)
        End If
    End Sub
    Public Sub T760_全出荷E集計A作成(E採用判定値A As Double)

        ' 1. T760_全出荷E集計A が存在すれば削除
        If Search_Table("T760_全出荷E集計A") Then
            DEL_table("T760_全出荷E集計A")
        End If
        ' 2. T760_全出荷E集計 をコピーして T760_全出荷E集計A を作成
        MySQL = "SELECT * INTO [T760_全出荷E集計A] FROM [T760_全出荷E集計]"
        SQL実行(MySQL)
        ' 3. E採用判定値A で E判定 を更新
        MySQL = "UPDATE [T760_全出荷E集計A] SET [E判定] = IIf([乱数] <= " & E採用判定値A & ", 'Yes', 'No'), [ECHK] = '*';"
        SQL実行(MySQL)

    End Sub

    Public Sub T760_全出荷I集計A作成(I採用判定値A As Double)

        ' 1. T760_全出荷I集計A が存在すれば削除
        If Search_Table("T760_全出荷I集計A") Then
            DEL_table("T760_全出荷I集計A")
        End If

        ' 2. T760_全出荷I集計 をコピーして T760_全出荷I集計A を作成
        MySQL = "SELECT * INTO [T760_全出荷I集計A] FROM [T760_全出荷I集計]"
        SQL実行(MySQL)

        ' 3. I採用判定値A で I判定 を更新
        MySQL = "UPDATE [T760_全出荷I集計A] SET [I判定] = IIf([乱数] <= " & I採用判定値A & ", 'Yes', 'No');"
        SQL実行(MySQL)

    End Sub

    Public Sub T900_ランク付け()

        ' ===== 1. T850* テーブルを削除 =====
        DEL_table("T850*")

        ' ===== 2. T850_全出荷E集計 を 出荷先 × GPL合計 で作成 =====
        MySQL = "SELECT 出荷先, Sum(GPL) AS GPL合計 INTO [T850_全出荷E集計] " &
                "FROM T900_計算対象 " &
                "GROUP BY 出荷先"
        SQL実行(MySQL)

        ' ===== 3. GPLEランク 列を追加 =====
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Using addCmd As New OleDbCommand(
                    "ALTER TABLE [T850_全出荷E集計] ADD COLUMN [GPLEランク] TEXT(10)", cn)
                    addCmd.ExecuteNonQuery()
                End Using
            End Using
        Catch
            ' 列が既に存在する場合は無視
        End Try

        ' ===== 4. GPL合計 を降順に読み込み累積比率でランク付け =====
        Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";"

        ' 4-1. GPL 全合計を取得
        Dim totalGPL As Double = 0
        Try
            Using cn As New OleDbConnection(connStr)
                cn.Open()
                Using cmd As New OleDbCommand(
                    "SELECT Sum(GPL合計) FROM [T850_全出荷E集計]", cn)
                    Dim result As Object = cmd.ExecuteScalar()
                    If result IsNot Nothing AndAlso Not IsDBNull(result) Then
                        totalGPL = Convert.ToDouble(result)
                    End If
                End Using
            End Using
        Catch ex As Exception
            MsgBox("T900_ランク付け: GPL合計取得エラー: " & ex.Message)
            Return
        End Try

        If totalGPL = 0 Then
            MsgBox("T900_ランク付け: T850_全出荷E集計 の GPL合計が 0 です。処理を中止します。")
            Return
        End If

        ' 4-2. ランク閾値（累積比率 %）を定義
        '      EIQ_A1ランク=50, EIQ_A2ランク=20, EIQ_Bランク=15, EIQ_Cランク=10, EIQ_Dランク=5
        Dim th_A1 As Double = EIQ_A1ランク                                      ' 50
        Dim th_A2 As Double = EIQ_A1ランク + EIQ_A2ランク                       ' 70
        Dim th_B As Double = EIQ_A1ランク + EIQ_A2ランク + EIQ_Bランク         ' 85
        Dim th_C As Double = EIQ_A1ランク + EIQ_A2ランク + EIQ_Bランク + EIQ_Cランク ' 95
        ' th_D = 100%（残り全て）

        ' 4-3. GPL合計 降順で読み込みながら累積比率を計算してランクを UPDATE
        Try
            Using cn As New OleDbConnection(connStr)
                cn.Open()

                Dim 累積GPL As Double = 0

                Using selCmd As New OleDbCommand(
                    "SELECT 出荷先, GPL合計 FROM [T850_全出荷E集計] ORDER BY GPL合計 DESC", cn)
                    Using rdr As OleDbDataReader = selCmd.ExecuteReader()

                        Dim updCmd As New OleDbCommand(
                            "UPDATE [T850_全出荷E集計] SET [GPLEランク] = ? WHERE [出荷先] = ?", cn)
                        updCmd.Parameters.Add(New OleDbParameter("?", OleDbType.VarChar, 10))
                        updCmd.Parameters.Add(New OleDbParameter("?", OleDbType.VarChar, 20))

                        While rdr.Read()
                            Dim dest As String = rdr("出荷先").ToString()
                            Dim gpl As Double = If(IsDBNull(rdr("GPL合計")), 0, Convert.ToDouble(rdr("GPL合計")))

                            累積GPL += gpl
                            Dim 累積比率 As Double = (累積GPL / totalGPL) * 100.0

                            Dim rank As String
                            If 累積比率 <= th_A1 Then
                                rank = "GPLE_A1"
                            ElseIf 累積比率 <= th_A2 Then
                                rank = "GPLE_A2"
                            ElseIf 累積比率 <= th_B Then
                                rank = "GPLE_B"
                            ElseIf 累積比率 <= th_C Then
                                rank = "GPLE_C"
                            Else
                                rank = "GPLE_D"
                            End If

                            updCmd.Parameters(0).Value = rank
                            updCmd.Parameters(1).Value = dest
                            updCmd.ExecuteNonQuery()
                        End While

                        updCmd.Dispose()
                    End Using
                End Using

                cn.Close()
            End Using
        Catch ex As Exception
            MsgBox("T900_ランク付け: ランク更新エラー: " & ex.Message)
            Return
        End Try

        ' ===== 5. T900_計算対象 の GPLEランク 列に T850_全出荷E集計 のランクを反映 =====
        ' GPLEランク 列が未存在の場合は追加
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Try
                    Using addCmd As New OleDbCommand(
                        "ALTER TABLE [T900_計算対象] ADD COLUMN [GPLEランク] TEXT(10)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                Catch
                    ' 既存の場合は無視
                End Try
            End Using
        Catch
        End Try

        MySQL = "UPDATE [T900_計算対象] " &
                "INNER JOIN [T850_全出荷E集計] ON [T900_計算対象].出荷先 = [T850_全出荷E集計].出荷先 " &
                "SET [T900_計算対象].[GPLEランク] = [T850_全出荷E集計].[GPLEランク];"
        SQL実行(MySQL)

    End Sub
    Public Sub T900_Iランク付け()

        ' ===== 1. T570* テーブルを削除 =====
        DEL_table("T570*")

        ' ===== 2. T570_全出荷I集計 を アイテム × GPL合計 で作成 =====
        MySQL = "SELECT アイテム, Sum(GPL) AS GPL合計 INTO [T570_全出荷I集計] " &
                "FROM T900_計算対象 " &
                "GROUP BY アイテム"
        SQL実行(MySQL)

        ' ===== 3. GPLIランク 列を追加 =====
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Using addCmd As New OleDbCommand(
                    "ALTER TABLE [T570_全出荷I集計] ADD COLUMN [GPLIランク] TEXT(10)", cn)
                    addCmd.ExecuteNonQuery()
                End Using
            End Using
        Catch
            ' 列が既に存在する場合は無視
        End Try

        ' ===== 4. GPL合計 を降順に読み込み累積比率でランク付け =====
        Dim connStr As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";"

        ' 4-1. GPL 全合計を取得
        Dim totalGPL As Double = 0
        Try
            Using cn As New OleDbConnection(connStr)
                cn.Open()
                Using cmd As New OleDbCommand(
                    "SELECT Sum(GPL合計) FROM [T570_全出荷I集計]", cn)
                    Dim result As Object = cmd.ExecuteScalar()
                    If result IsNot Nothing AndAlso Not IsDBNull(result) Then
                        totalGPL = Convert.ToDouble(result)
                    End If
                End Using
            End Using
        Catch ex As Exception
            MsgBox("T900_Iランク付け: GPL合計取得エラー: " & ex.Message)
            Return
        End Try

        If totalGPL = 0 Then
            MsgBox("T900_Iランク付け: T570_全出荷I集計 の GPL合計が 0 です。処理を中止します。")
            Return
        End If

        ' 4-2. ランク閾値（累積比率 %）を定義
        '      EIQ_A1ランク=50, EIQ_A2ランク=20, EIQ_Bランク=15, EIQ_Cランク=10, EIQ_Dランク=5
        Dim th_A1 As Double = EIQ_A1ランク                                           ' 50
        Dim th_A2 As Double = EIQ_A1ランク + EIQ_A2ランク                            ' 70
        Dim th_B As Double = EIQ_A1ランク + EIQ_A2ランク + EIQ_Bランク              ' 85
        Dim th_C As Double = EIQ_A1ランク + EIQ_A2ランク + EIQ_Bランク + EIQ_Cランク ' 95
        ' th_D = 100%（残り全て）

        ' 4-3. GPL合計 降順で読み込みながら累積比率を計算してランクを UPDATE
        Try
            Using cn As New OleDbConnection(connStr)
                cn.Open()

                Dim 累積GPL As Double = 0

                Using selCmd As New OleDbCommand(
                    "SELECT アイテム, GPL合計 FROM [T570_全出荷I集計] ORDER BY GPL合計 DESC", cn)
                    Using rdr As OleDbDataReader = selCmd.ExecuteReader()

                        Dim updCmd As New OleDbCommand(
                            "UPDATE [T570_全出荷I集計] SET [GPLIランク] = ? WHERE [アイテム] = ?", cn)
                        updCmd.Parameters.Add(New OleDbParameter("?", OleDbType.VarChar, 10))
                        updCmd.Parameters.Add(New OleDbParameter("?", OleDbType.VarChar, 20))

                        While rdr.Read()
                            Dim item As String = rdr("アイテム").ToString()
                            Dim gpl As Double = If(IsDBNull(rdr("GPL合計")), 0, Convert.ToDouble(rdr("GPL合計")))

                            累積GPL += gpl
                            Dim 累積比率 As Double = (累積GPL / totalGPL) * 100.0

                            Dim rank As String
                            If 累積比率 <= th_A1 Then
                                rank = "GPLI_A1"
                            ElseIf 累積比率 <= th_A2 Then
                                rank = "GPLI_A2"
                            ElseIf 累積比率 <= th_B Then
                                rank = "GPLI_B"
                            ElseIf 累積比率 <= th_C Then
                                rank = "GPLI_C"
                            Else
                                rank = "GPLI_D"
                            End If

                            updCmd.Parameters(0).Value = rank
                            updCmd.Parameters(1).Value = item
                            updCmd.ExecuteNonQuery()
                        End While

                        updCmd.Dispose()
                    End Using
                End Using

                cn.Close()
            End Using
        Catch ex As Exception
            MsgBox("T900_Iランク付け: ランク更新エラー: " & ex.Message)
            Return
        End Try

        ' ===== 5. T900_計算対象 の GPLIランク 列に T570_全出荷I集計 のランクを反映 =====
        ' GPLIランク 列が未存在の場合は追加
        Try
            Using cn As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyDB & ";")
                cn.Open()
                Try
                    Using addCmd As New OleDbCommand(
                        "ALTER TABLE [T900_計算対象] ADD COLUMN [GPLIランク] TEXT(10)", cn)
                        addCmd.ExecuteNonQuery()
                    End Using
                Catch
                    ' 既存の場合は無視
                End Try
            End Using
        Catch
        End Try

        MySQL = "UPDATE [T900_計算対象] " &
                "INNER JOIN [T570_全出荷I集計] ON [T900_計算対象].アイテム = [T570_全出荷I集計].アイテム " &
                "SET [T900_計算対象].[GPLIランク] = [T570_全出荷I集計].[GPLIランク];"
        SQL実行(MySQL)

    End Sub

    Public Sub T900_ランク集計()
        '1. T900_計算対象 を 進行連番/GPLEランク/GPLIランク ごとに集計
        MySQL = "SELECT T900_計算対象.進行連番, T900_計算対象.GPLEランク, T900_計算対象.GPLIランク, Count(T900_計算対象.行連番) AS 行数, Sum(T900_計算対象.G行) AS 出庫回数, Sum(T900_計算対象.Gバ) AS バラ数, Sum(T900_計算対象.Gケ) AS ケース数, Sum(T900_計算対象.GPL) AS PL数, Sum(T900_計算対象.G容) AS 容積, Sum(T900_計算対象.G重) AS 重量 FROM T900_計算対象 GROUP BY T900_計算対象.進行連番, T900_計算対象.GPLEランク, T900_計算対象.GPLIランク;"
        SQL実行(MySQL)

        '2. T570_全出荷I集計 を GPLIランク ごとに アイテム数 を集計
        MySQL = "SELECT T570_全出荷I集計.GPLIランク, Count(T570_全出荷I集計.[アイテム]) AS アイテム数 FROM T570_全出荷I集計 GROUP BY T570_全出荷I集計.GPLIランク;"
        SQL実行(MySQL)

        '3. T900_計算対象 から行数・バラ数を集計
        MySQL = "SELECT Count(T900_計算対象.行連番) AS 行数, Sum(T900_計算対象.Gバ) AS バラ数 FROM T900_計算対象;"
        SQL実行(MySQL)

        '4. T900_計算対象 を GPLEランク/GPLIランク ごとに集計
        MySQL = "SELECT T900_計算対象.GPLEランク, T900_計算対象.GPLIランク, Count(T900_計算対象.行連番) AS 行数, Sum(T900_計算対象.G行) AS 出庫回数, Sum(T900_計算対象.Gバ) AS バラ数, Sum(T900_計算対象.Gケ) AS ケース数, Sum(T900_計算対象.GPL) AS PL数, Sum(T900_計算対象.G容) AS 容積, Sum(T900_計算対象.G重) AS 重量 FROM T900_計算対象 GROUP BY T900_計算対象.GPLEランク, T900_計算対象.GPLIランク;"
        SQL実行(MySQL)



    End Sub

End Module